using System;
using Tarkin.InfrastructureLibrary.Core.Basic;
using Tarkin.InfrastructureLibrary.Core.PrimitiveTypes;
using Tarkin.InfrastructureLibrary.Tests.Core.Basic.TestUtilities.ConcreteClasses;
using NUnit.Framework;

namespace Tarkin.InfrastructureLibrary.Tests.Core.Basic
{
    /// <summary>
    /// OperationTests is the NUnit TestFixture for the Tarkin.InfrastructureLibrary.Core.Basic.Operation class.
    /// </summary>
    [TestFixture]
    public class OperationTests
    {
        [Test]
        public void TestOverloadedConstructorOneParameter ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            Operation operation = new Operation ( typedElement );

            Assert.IsNotNull ( operation );
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestOverloadedConstructorOneParameterNullValue ()
        {
            Operation operation = new Operation ( null );

            Assert.IsNotNull ( operation );
        }

        [Test]
        public void TestOverloadedConstructorTwoParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            Operation operation = new Operation ( typedElement, multiplicityElement );

            Assert.IsNotNull ( operation );
        }

        [Test]
        public void TestOverloadedConstructorThreeParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            Class owningClass = new Class ( "Owning Class name" );
            Operation operation = new Operation ( typedElement, multiplicityElement, owningClass );

            Assert.IsNotNull ( operation );
        }

        [Test]
        public void TestOverloadedConstructorFiveParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            Operation operation = new Operation ( typedElement, true, true, 23, unlimitedNatural );

            Assert.IsNotNull ( operation );
            Assert.AreEqual ( "Typed Element name", operation.Name );
            Assert.AreEqual ( true, operation.IsOrdered );
            Assert.AreEqual ( true, operation.IsUnique );
            Assert.AreEqual ( 23, operation.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, operation.Upper.Value );
        }

        [Test]
        public void TestOverloadedConstructorSixParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            Class owningClass = new Class ( "Owning Class name" );
            Operation operation = new Operation ( typedElement, true, true, 23, unlimitedNatural, owningClass );

            Assert.IsNotNull ( operation );
            Assert.AreEqual ( "Typed Element name", operation.Name );
            Assert.AreEqual ( true, operation.IsOrdered );
            Assert.AreEqual ( true, operation.IsUnique );
            Assert.AreEqual ( 23, operation.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, operation.Upper.Value );
            Assert.AreEqual ( "Owning Class name", operation.Class.Name );
        }

        [Test]
        public void TestTypeProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Type name" );
            ConcreteType type = new ConcreteType ( "Type name" );
            Operation operation = new Operation ( typedElement );

            operation.Type = type;

            Assert.IsNotNull ( operation.Type );
            Assert.AreEqual ( "Type name", operation.Type.Name );
        }

        [Test]
        public void TestOwnedParametersProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            Parameter parameter = new Parameter ( typedElement );
            Operation operation = new Operation ( typedElement );

            Assert.IsNotNull ( operation.OwnedParameters );
            
            operation.OwnedParameters.Add ( parameter );

            Assert.IsTrue ( operation.OwnedParameters.Contains ( parameter ) );
        }

        [Test]
        public void TestRaisedExceptionsProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            ConcreteType type = new ConcreteType ( "Type name" );
            Operation operation = new Operation ( typedElement );

            Assert.IsNotNull ( operation.RaisedExceptions );

            operation.RaisedExceptions.Add ( type );

            Assert.IsTrue ( operation.RaisedExceptions.Contains ( type ) );
        }

        [Test]
        public void TestClassProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            Class owningClass = new Class ( "Owning Class name" );
            Operation operation = new Operation ( typedElement );

            operation.Class = owningClass;

            Assert.IsNotNull ( operation.Class );
            Assert.AreEqual ( "Owning Class name", operation.Class.Name );
        }

        [Test]
        public void TestNameProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ();
            Operation operation = new Operation ( typedElement );

            operation.Name = "Name";

            Assert.AreEqual ( "Name", operation.Name );
        }

    }
}
